﻿#light

module PubSim.Assistant

open Microsoft.FSharp.Control
open System.Collections.Generic
open System.Threading
open PubSim.Glasses
open PubSim.Cups
open PubSim.Table

type Assistant(outputQueue : Queue<string>, tables : array<PubSim.Table.Table>, glasses : PubSim.Glasses.Glasses, cups : PubSim.Cups.Cups) =
    let timeTakenForBreak = 5000 // milliseconds
    let timeToCleanGlass = 250 // milliseconds
    let timeToCleanCup = 250 // milliseconds
  
    member t.CollectGlassesFromTable (table:PubSim.Table.Table, glasses:PubSim.Glasses.Glasses) =
        let numGlassesFetchedFromTable = table.FetchAllGlassesFromTable()
        numGlassesFetchedFromTable
  
    member t.CollectCupsFromAllTable (table:PubSim.Table.Table, cups:PubSim.Cups.Cups) =
        let numCupsFetchedFromTable = table.FetchAllCupsFromTable()
        numCupsFetchedFromTable
  
    member t.CleanGlasses(numGlassesFetched:int) =
        outputQueue.Enqueue(sprintf "Assistant: Cleaning %d glasses" numGlassesFetched)
        Thread.Sleep(numGlassesFetched * timeToCleanGlass)
  
    member t.CleanCups(numCupsFetched:int) =
        outputQueue.Enqueue(sprintf "Assistant: Cleaning %d cups" numCupsFetched)
        Thread.Sleep(numCupsFetched * timeToCleanCup)
         
    member t.TakeBreak() =
        outputQueue.Enqueue(sprintf "Assistant: Taking break for %d seconds" (timeTakenForBreak/1000))
        Thread.Sleep(timeTakenForBreak)       
              
    member t.Start() =

        while (true) do
            let mutable numTotalGlassesFetched = 0
            let mutable numTotalCupsFetched = 0
        
            // Pause in the beginning so that the Assistant does not start cleaning before
            // anything is dirty!
            t.TakeBreak()
            
            // Cycle thru each table
            for i = 0 to (PubSim.Table.maxNumTables-1) do
                let mutable numGlassesFetched = 0
                let mutable numCupsFetched = 0
                
                // Fetch all glasses from the specific table
                numGlassesFetched <- tables.[i].FetchAllGlassesFromTable()
                outputQueue.Enqueue(sprintf "Assistant: Collected %d Glasses From Table %d" numGlassesFetched i)
                
                // Fetch all cups from the specific table
                numCupsFetched <- tables.[i].FetchAllCupsFromTable()
                outputQueue.Enqueue(sprintf "Assistant: Collected %d Cups From Table %d" numGlassesFetched i)
                
                numTotalGlassesFetched <- numTotalGlassesFetched + numGlassesFetched
                numTotalCupsFetched <- numTotalCupsFetched + numCupsFetched
            
            // At this point, we have fetched all the glasses and cups from ALL tables,
            // so clean them.
            t.CleanGlasses(numTotalGlassesFetched)

            t.CleanCups(numTotalCupsFetched)
            
            // Added the cleaned glasses and cups to the cupboard.
            glasses.AddGlasses(numTotalGlassesFetched)
            outputQueue.Enqueue(sprintf "Assistant: Added %d Glasses To The Cupboard" numTotalGlassesFetched)

            cups.AddCups(numTotalCupsFetched)
            outputQueue.Enqueue(sprintf "Assistant: Added %d Cups To The Cupboard" numTotalCupsFetched)
